
uniform vec2  SizeRatio;

shader TexVS(in vec2 Position:0, out vec2 vTexCoords)
{
    vTexCoords = Position*SizeRatio;
    gl_Position = vec4(2*Position-1, .0, 1.);
}

sampler WaveSampler {
    MinFilter=point;
    MagFilter=point;
    WrapS=mirroredRepeat;
    WrapT=mirroredRepeat;
} u_t, u_pt, impulse, u_stepConst;

uniform WaveSimParams {
    float invDhSq;
    float cSq;
    float dt;
    float impulsePre;
} SimParams;

shader WaveFS(in vec2 vTexCoords, out vec4 u_nt)
{
    ivec2 iTexCoords=ivec2(vTexCoords*textureSize(u_t, 0));
    ivec2 lap[4]={ ivec2(1,0), ivec2(-1,0), ivec2(0,1), ivec2(0,-1) };

    float waveStepConst=texelFetch(u_stepConst, iTexCoords, 0).r;
    waveStepConst*=waveStepConst*SimParams.invDhSq*SimParams.cSq*SimParams.dt*SimParams.dt;
    float tmp1=2*texelFetch(u_t, iTexCoords, 0).r;
    float tmp=dot(textureGatherOffsets(u_t, vTexCoords, lap), vec4(1));
    tmp-=2*tmp1;
    tmp*=5;
    tmp-=dot(textureGatherOffsets(u_pt, vTexCoords, lap), vec4(1));
    float prevTex=texelFetch(u_pt, iTexCoords, 0).r;
    tmp+=4*prevTex;
    tmp*=waveStepConst*0.25;
    tmp+=tmp1-prevTex;

    float imp=-4*texelFetch(impulse, iTexCoords, 0).r;
    imp+=dot(textureGatherOffsets(impulse, vTexCoords, lap),vec4(1));
    imp*=SimParams.impulsePre*SimParams.invDhSq*SimParams.cSq*SimParams.dt;
    
    u_nt.r = tmp + imp;
}

uniform ivec2 Direction;

shader GaussianFS(in vec2 vTexCoords, out vec4 filtered)
{
    ivec2 n4[4]={ ivec2(1,0), ivec2(-1,0), ivec2(0,1), ivec2(0,-1) };
    vec4 vals=textureGatherOffsets(u_t, vTexCoords, n4);
    
    ivec2 iTexCoords=ivec2(vTexCoords*textureSize(u_t, 0));
    float wght=texelFetch(u_stepConst, iTexCoords, 0).r > 1 ? 0.334118422095951 : 1;
    float otherWghts=0.5*(1-wght);

    filtered.r = otherWghts*dot(vals, Direction.xxyy) +
        wght*texelFetch(u_t, iTexCoords, 0).r;
}

program WaveSim {
    vs(420)=TexVS();
    fs(420)=WaveFS();
};

program GaussianFilter {
    vs(420)=TexVS();
    fs(420)=GaussianFS();
};
